package de.tub.bazinga.player;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import processing.core.PApplet;
import SimpleOpenNI.SimpleOpenNI;
import de.tub.bazinga.event.NewPlayerEvent;
import de.tub.bazinga.eventbus.DefaultEventBus;
import de.tub.bazinga.object.Color;
import de.tub.bazinga.object.ColorPool;
import de.tub.bazinga.object.TargetDefinition;
import de.tub.bazinga.object.interf.Drawable;

public class PlayerPool implements Drawable {

	private final ColorPool playerColors;

	private final SimpleOpenNI context;

	private final Map<Integer, Player> activePlayers;
	private final Map<Integer, Player> inactivePlayers;

	private boolean dynamicCircle;

	public PlayerPool(SimpleOpenNI context) {
		this.context = context;

		playerColors = new ColorPool();
		this.dynamicCircle = true;
		// source of colors: http://www.visibone.com/colorlab/
		playerColors.addColor(new Color(255, 102, 0, 255)); // Orange-Orange-Red
		playerColors.addColor(new Color(0, 255, 102, 255)); // Teal-Teal-Green
		playerColors.addColor(new Color(0, 153, 255, 255)); // Azure-Azure-Cyan
		playerColors.addColor(new Color(102, 0, 255, 255)); // Violet-Violet-Blue

		activePlayers = new ConcurrentHashMap<Integer, Player>();
		inactivePlayers = new ConcurrentHashMap<Integer, Player>();
	}

	public void createNewPlayer(int userId) {
		Player newPlayer = new Player(userId, context);
		inactivePlayers.put(userId, newPlayer);

		NewPlayerEvent npe = new NewPlayerEvent(newPlayer);
		DefaultEventBus.getInstance().fireEvent(npe);
	}

	public boolean moveToActivePlayers(int userId) {
		Player player = inactivePlayers.get(userId);
		if (player != null && playerColors.hasNextColor()) {
			inactivePlayers.remove(userId);
			player.setColor(playerColors.getNextColor());
			activePlayers.put(userId, player);
			player.updateCirclePosition();
			return true;
		}
		return false;
	}

	public boolean moveToInactivePlayers(int userId) {
		Player player = activePlayers.get(userId);
		if (player != null) {
			activePlayers.remove(userId);
			playerColors.addColor(player.getColor());
			player.setColor(Player.INACTIVE_COLOR);
			inactivePlayers.put(userId, player);

			return true;
		}
		return false;
	}

	public boolean isActivePlayerSlotAvailable() {
		return playerColors.hasNextColor();
	}

	public boolean isActivePlayer(int userId) {
		return activePlayers.containsKey(userId);
	}

	public boolean isInactivePlayer(int userId) {
		return inactivePlayers.containsKey(userId);
	}

	@Override
	public void draw(PApplet window) {
		ArrayList<Player> allPlayers = new ArrayList<Player>();
		allPlayers.addAll(activePlayers.values());
		allPlayers.addAll(inactivePlayers.values());

		for (Player player : allPlayers) {
			if (dynamicCircle || !player.getCircle().hasPosition()) {
				player.updateCirclePosition();
			}
			player.draw(window);
		}
	}

	public void setTargetsForAllPlayers(Set<TargetDefinition> targets) {
		for (Integer key : activePlayers.keySet()) {
			activePlayers.get(key).removeTargets();
			activePlayers.get(key).addTargetsByDefinition(targets);
		}
		for (Integer key : inactivePlayers.keySet()) {
			activePlayers.get(key).removeTargets();
			activePlayers.get(key).addTargetsByDefinition(targets);
		}
	}

	public void removeAllTargets() {
		for (Integer key : activePlayers.keySet()) {
			activePlayers.get(key).removeTargets();
		}
		for (Integer key : inactivePlayers.keySet()) {
			inactivePlayers.get(key).removeTargets();
		}
	}

	public void setTargetForAllPlayers(TargetDefinition target) {
		for (Integer key : activePlayers.keySet()) {
			activePlayers.get(key).removeTargets();
			activePlayers.get(key).addTargetByDefinition(target);
		}
		for (Integer key : inactivePlayers.keySet()) {
			activePlayers.get(key).removeTargets();
			activePlayers.get(key).addTargetByDefinition(target);
		}
	}

	public Set<Player> getAllPlayer() {
		Set<Player> returnSet = new HashSet<Player>();
		returnSet.addAll(activePlayers.values());
		returnSet.addAll(inactivePlayers.values());
		return returnSet;
	}

	public void setDynamicCircle(boolean dynamic) {
		dynamicCircle = dynamic;
	}

	public boolean isDynamicCircle() {
		return dynamicCircle;
	}

	public Collection<Player> activePlayers() {
		return activePlayers.values();
	}

	public void removePlayer(int userId) {
		inactivePlayers.remove(userId);
	}

}
